package com.toobigtofail.utility
{
	import Box2D.Common.Math.b2Vec2;
	
	import com.toobigtofail.shapes.Line;
	import com.toobigtofail.utility.Util;
	
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Text;
	import net.flashpunk.utils.Draw;
	import net.flashpunk.utils.Input;
	
	public class LineDrawer extends Entity
	{
		private static const DRAW_INTERVAL:Number = 0.01; // seconds
		
		private var _drawTimer:Number = 0;
		private var _drawVerts:Array = new Array;
		private var _startingDrawCounter:Number = 0;
		private var _drawCounter:Number = _startingDrawCounter;
		private var _drawCountDisplay:Entity = new Entity(0,0, new Text(""));
		
		private var _drawAreaTL:b2Vec2;
		private var _drawAreaWidth:int;
		private var _drawAreaHeight:int;
		
		private var _isDone:Boolean = false;
		private var _isShowingCounter:Boolean = false;
		
		public function LineDrawer(linePower:Number, drawAreaTL:b2Vec2 = null, drawAreaWidth:int = -1, drawAreaHeight:int = -1) {
			_drawAreaTL = null == drawAreaTL ? new b2Vec2(0,0) : drawAreaTL;
			_drawAreaWidth = -1 == drawAreaWidth ? 0 : drawAreaWidth;
			_drawAreaHeight = -1 == drawAreaHeight ? 0 : drawAreaHeight;
		
			_startingDrawCounter = linePower;
			_drawCounter = linePower;
		}
		
		override public function update():void {
			super.update();
			
			if (!_isDone && ((Input.mouseUp && _drawVerts.length) || (Input.mouseDown && isMouseInDrawArea() && !capture()))) {
				_isDone = true;
				hideCounter();
			}
		}
		
		override public function render():void {
			super.render();
			
			for (var i:int = 0; i < _drawVerts.length-1; i++) {
				var p1:b2Vec2 = _drawVerts[i];
				var p2:b2Vec2 = _drawVerts[i+1];
				Draw.linePlus(p1.x, p1.y, p2.x, p2.y, 0xFFFFFFFF, 1, 3);
			}
			if (_drawVerts.length && isMouseInDrawArea()) {
				var p:b2Vec2 = _drawVerts[_drawVerts.length-1];
				Draw.linePlus(p.x, p.y, Input.mouseX, Input.mouseY, 0xFFFFFFFF, 1, 3);
			}
		}
		
		public function capture():Boolean {
			if (!_isShowingCounter) {
				showCounter();
			}
			if (_drawCounter <= 0) {
				return false;
			}
			
			displayCounter();
			_drawTimer -= FP.elapsed;
			if (!_isDone && _drawTimer <= 0) {
				if (!_drawVerts.length || !Util.isSameVec(_drawVerts[_drawVerts.length-1], new b2Vec2(Input.mouseX, Input.mouseY))) {
					addVert(new b2Vec2(Input.mouseX, Input.mouseY));
				}
				_drawTimer = DRAW_INTERVAL;
			}
			return true;
		}
		
		public function finalizeLine():Line {
			if (_drawVerts.length > 1) {
				var x:Number = (_drawVerts[0] as b2Vec2).x;
				var y:Number = (_drawVerts[0] as b2Vec2).y;
				var line:Line = new Line(x,y, Line.absoluteToRelative(x,y,_drawVerts.concat()));
				reset();
				return line;
			}
			return null;
		}
		
		public function reset():void {
			hideCounter();
			
			_drawTimer = 0;
			_drawVerts = new Array;
			//_drawCounter = _startingDrawCounter;
			_isDone = false;
		}
		
		
		
		private function addVert(vert:b2Vec2):void {
			if (_drawVerts.length) {				
				var p:b2Vec2 = vert.Copy();
				p.Subtract(_drawVerts[_drawVerts.length-1]);
				_drawCounter -= Math.sqrt(p.LengthSquared());
			}
			_drawVerts.push(vert);
		}
		
		private function displayCounter():void {
			_drawCountDisplay.x = Input.mouseX + 20;
			_drawCountDisplay.y = Input.mouseY + 20;
			
			_drawCountDisplay.graphic = new Text(Math.floor(_drawCounter).toFixed());
		}
		
		private function isMouseInDrawArea():Boolean {
			return Util.inRect(new b2Vec2(Input.mouseX, Input.mouseY), _drawAreaTL, _drawAreaWidth, _drawAreaHeight);
		}
		
		public function showCounter():void {
			FP.world.add(_drawCountDisplay);
			_isShowingCounter = true;
		}
		
		public function hideCounter():void {
			FP.world.remove(_drawCountDisplay);
			_isShowingCounter = false;
		}
		
		public function set linePower(ml:Number):void { 
			_startingDrawCounter = ml;
			_drawCounter = ml;
		}
		public function setDrawArea(tl:b2Vec2, w:int, h:int):void {
			_drawAreaTL = tl;
			_drawAreaWidth = w;
			_drawAreaHeight = h;
		}
		
		public function get isDone():Boolean { return _isDone; }
		public function get remainingLine():Number { return _drawCounter; }
	}
}